package test;

import java.io.ByteArrayOutputStream;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.Security;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;
import java.util.zip.CRC32;

import javax.crypto.Cipher;

import org.bouncycastle.jce.provider.BouncyCastleProvider;

import com.sun.org.apache.xml.internal.security.utils.Base64;

public class RSAEncryption {
private static final String KEY_ALGORITHM = "RSA";     
	private static final String PUBLIC_KEY = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDNSSX8/YQoMcgm3RCo/ZXXyNwGIMhEdWu6e7cz"
			+ "dwJK4Rj9Vb2eTM/ChRRtVFGyti3PY+AYgDL/p4ncfgmH0wKTZwm0BpwDfaCE+uwOIBtPo73PctVv"
			+ "pHFjXhLbKqwHDOMTMrRraxpwIv+y16GUME+/Xs+lajeQwwHDcf452xkd9QIDAQAB";   
	private static final String PRIVATE_KEY = "MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBAM1JJfz9hCgxyCbdEKj9ldfI3AYg"
			+ "yER1a7p7tzN3AkrhGP1VvZ5Mz8KFFG1UUbK2Lc9j4BiAMv+nidx+CYfTApNnCbQGnAN9oIT67A4g"
			+ "G0+jvc9y1W+kcWNeEtsqrAcM4xMytGtrGnAi/7LXoZQwT79ez6VqN5DDAcNx/jnbGR31AgMBAAEC"
			+ "gYEAnIFkANiWZL5vRZHMHcoW7wgnFlTv2aFbnDStmwLkMIokLx+rDICq9DXZOPDLyF+z1STjuEok"
			+ "l1v3cq50PaTVlIVNgEykHaNE35Pv6NHywXCzlnKOwqfYRW5rFxQcMFUfrelMd9atGGfvmCBmW8ol"
			+ "1hqoS/0sH/Hk/qRkuNHiFRECQQDwVQGZgqXKjL9bM/6yG6nCFjwK4HZhbjeOunS8Ge0F0xo4Qrj5"
			+ "t+W0iPZL91kvEHQG98OlxXO+cv9heu9xrtEnAkEA2qs9nZZp0Kim22w/DMtOuFT3PtvXRKMQjwJ1"
			+ "O7Tbxz3dgqPcxNrzv689f6Rt88Ybhr5U9fsitHrXnADgVouRgwJAD0M2wMr9QGnD1UTuDd2X4E2N"
			+ "LpumqPVY7eWFeFSlKtOHPL9wA9vb6KUyDwz8SvLei3q8oBB0E0o2Ubh+8FdLzQJBAKXGNEwH/+hk"
			+ "Mzsd8R6t8tvj7h0FZUlvpdoFLwM4tXVy/T9RIslKhIfJPoJKEeFBSxT3rkldPo48osBuGaUC4ikC"
			+ "QQCQlsjC4c1tODKOKOkWWriQ+rmS+jtyfk/2zXlv1Fl806lx+SFI5lbCUhWWhZZ8PxyGFbcayG7L"
			+ "0gmj9pR8OoJd";  

/**
 * RSA最大加密明文大小
 */
private static final int MAX_ENCRYPT_BLOCK = 117;

/**
 * RSA最大解密密文大小
 */
private static final int MAX_DECRYPT_BLOCK = 128;
/**
 * Provider
 */
private static final String PROVIDER = "BC";

public static void main(String[] args) throws Exception{   
    //读取内容
	StringBuffer info = new StringBuffer("明文1234567");
    
    CRC32 CRCout =new CRC32();//定义校验对象
	CRCout.update(info.toString().getBytes());			
	Long crc=CRCout.getValue();//返回校验值给crc
   
	StringBuffer suf = info.append("#CRC#").append(String.valueOf(crc));
	
	//加密   
    String encryData = encryptByPublicKey(PUBLIC_KEY,suf.toString());   
    System.out.println(encryData); 
    HttpTest.userSend(encryData);
}   

/**
 * 产生密钥对并存放在Map<String,String>中
 * @return
 * @throws NoSuchAlgorithmException
 */
public static Map<String,String> genKey() throws NoSuchAlgorithmException{   
    Map<String,String> keyMap = new HashMap<String,String>();   
    KeyPairGenerator keygen = KeyPairGenerator.getInstance(KEY_ALGORITHM);   
    SecureRandom random = new SecureRandom();   
    // random.setSeed(keyInfo.getBytes());   
    // 初始加密，512位已被破解，用1024位,最好用2048位   
    keygen.initialize(1024, random);   
    // 取得密钥对   
    KeyPair kp = keygen.generateKeyPair();   
    RSAPrivateKey privateKey = (RSAPrivateKey)kp.getPrivate();   
    String privateKeyString = Base64.encode(privateKey.getEncoded());   
    RSAPublicKey publicKey = (RSAPublicKey)kp.getPublic();    
    String publicKeyString = Base64.encode(publicKey.getEncoded());   
    keyMap.put(PUBLIC_KEY, publicKeyString);   
    keyMap.put(PRIVATE_KEY, privateKeyString);   
    return keyMap;   
}   
  
/**
 * 将字符串密钥转化成RSAPublicKey类型的公钥
 * @param publicKey
 * @return
 * @throws Exception
 */
public static RSAPublicKey getPublicKey(String publicKey) throws Exception{   
    byte[] keyBytes = Base64.decode(publicKey);   
    X509EncodedKeySpec spec = new X509EncodedKeySpec(keyBytes);   
    KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);   
    return (RSAPublicKey) keyFactory.generatePublic(spec);   
}   
  
/**
 * 将字符串密钥转化成RSAPrivateKey类型的私钥
 * @param privateKey
 * @return
 * @throws Exception
 */
public static RSAPrivateKey getPrivateKey(String privateKey) throws Exception{   
    byte[] keyBytes = Base64.decode(privateKey);   
    PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(keyBytes);   
    KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);   
    return (RSAPrivateKey) keyFactory.generatePrivate(spec);   
}  

/**
 * <P>
 * 私钥解密
 * </p>
 * 
 * @param encryptedData 已加密数据
 * @param privateKey 私钥(BASE64编码)
 * @return
 * @throws Exception
 */
public static byte[] decryptByPrivateKey(String privtKey,String encyptData)
        throws Exception {
	
	Security.addProvider(new BouncyCastleProvider()); //增加PROVIDER  
	RSAPrivateKey privateKey = getPrivateKey(privtKey);
	byte[] encryptedData = Base64.decode(encyptData);
    Cipher cipher = Cipher.getInstance(KEY_ALGORITHM,PROVIDER);
    cipher.init(Cipher.DECRYPT_MODE, privateKey);
    int inputLen = encryptedData.length;
    ByteArrayOutputStream out = new ByteArrayOutputStream();
    int offSet = 0;
    byte[] cache;
    int i = 0;
    // 对数据分段解密
    while (inputLen - offSet > 0) {
        if (inputLen - offSet > MAX_DECRYPT_BLOCK) {
            cache = cipher.doFinal(encryptedData, offSet, MAX_DECRYPT_BLOCK);
        } else {
            cache = cipher.doFinal(encryptedData, offSet, inputLen - offSet);
        }
        out.write(cache, 0, cache.length);
        i++;
        offSet = i * MAX_DECRYPT_BLOCK;
    }
    byte[] decryptedData = out.toByteArray();
    out.close();
    return decryptedData;
}

/**
 * <p>
 * 公钥解密
 * </p>
 * 
 * @param encryptedData 已加密数据
 * @param publicKey 公钥(BASE64编码)
 * @return
 * @throws Exception
 */
public static byte[] decryptByPublicKey(String pubKey,String  encyptData)
        throws Exception {
	Security.addProvider(new BouncyCastleProvider()); //增加PROVIDER 
	RSAPublicKey publicKey = getPublicKey(pubKey);
	byte[] encryptedData = Base64.decode(encyptData);
    Cipher cipher = Cipher.getInstance(KEY_ALGORITHM,PROVIDER);
    cipher.init(Cipher.DECRYPT_MODE, publicKey);
    int inputLen = encryptedData.length;
    ByteArrayOutputStream out = new ByteArrayOutputStream();
    int offSet = 0;
    byte[] cache;
    int i = 0;
    // 对数据分段解密
    while (inputLen - offSet > 0) {
        if (inputLen - offSet > MAX_DECRYPT_BLOCK) {
            cache = cipher.doFinal(encryptedData, offSet, MAX_DECRYPT_BLOCK);
        } else {
            cache = cipher.doFinal(encryptedData, offSet, inputLen - offSet);
        }
        out.write(cache, 0, cache.length);
        i++;
        offSet = i * MAX_DECRYPT_BLOCK;
    }
    byte[] decryptedData = out.toByteArray();
    out.close();
    return decryptedData;
}

/**
 * <p>
 * 公钥加密
 * </p>
 * 
 * @param sourceData 源数据
 * @param publicKey 公钥
 * @return
 * @throws Exception
 */
public static String encryptByPublicKey(String pubKey,String sourceData)
        throws Exception {
	Security.addProvider(new BouncyCastleProvider()); //增加PROVIDER
	RSAPublicKey publicKey = getPublicKey(pubKey);
	byte[] data = sourceData.getBytes("utf-8");
    // 对数据加密
    Cipher cipher = Cipher.getInstance(KEY_ALGORITHM,PROVIDER);
    cipher.init(Cipher.ENCRYPT_MODE, publicKey);
    int inputLen = data.length;
    ByteArrayOutputStream out = new ByteArrayOutputStream();
    int offSet = 0;
    byte[] cache = null;
    int i = 0;
    // 对数据分段加密
    while (inputLen - offSet > 0) {
        if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {
            cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK);
        } else {
            cache = cipher.doFinal(data, offSet, inputLen - offSet);
        }
        out.write(cache, 0, cache.length);
        i++;
        offSet = i * MAX_ENCRYPT_BLOCK;
    }
    byte[] encryptedData = out.toByteArray();
    out.close();
    String result = Base64.encode(encryptedData);
    return result;
}

/**
 * <p>
 * 私钥加密
 * </p>
 * 
 * @param sourceData 源数据
 * @param privateKey 私钥
 * @return
 * @throws Exception
 */
public static String encryptByPrivateKey(String privtKey,String sourceData)
        throws Exception {
	Security.addProvider(new BouncyCastleProvider()); //增加PROVIDER
	RSAPrivateKey privateKey = getPrivateKey(privtKey);
	byte[] data = sourceData.getBytes("utf-8");
	Cipher cipher = Cipher.getInstance(KEY_ALGORITHM,PROVIDER);
	cipher.init(Cipher.ENCRYPT_MODE, privateKey);
	int inputLen = data.length;
	ByteArrayOutputStream out = new ByteArrayOutputStream();
	int offSet = 0;
	byte[] cache;
	int i = 0;
	// 对数据分段加密
	while (inputLen - offSet > 0) {
		if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {
			cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK);
		} else {
			cache = cipher.doFinal(data, offSet, inputLen - offSet);
		}
		out.write(cache, 0, cache.length);
		i++;
		offSet = i * MAX_ENCRYPT_BLOCK;
	}
	byte[] encryptedData = out.toByteArray();
	out.close();
	String result = Base64.encode(encryptedData);
	return result;
 }

}
